   #include <stdio.h>
   #include <stdlib.h>  /* for  atof() */
   #include <math.h> /*  sin, exp, and pow */
   #include "defines.h"
#include <errno.h>
#include <fenv.h>

   int getop(char []);
   void push(double);
   double pop(void);
   void clear(void);


   /* reverse Polish calculator */
   int main()
   {
	
	  size_t size;
	  double variable[26];  /* variable stack */
       int type;
       double op2,outcome;
       char *s ;
	  int dontprintme=0;
	  
        feclearexcept(FE_ALL_EXCEPT);

    	   int i=0;
	   int len=0;
	   while (1)
	    {
		 i=0;
		 //     	 len=getline(s,&size,stdin);// != EOF ???? @bug
		 len=getline(&s,&size,stdin);
		 while	   ( (i<len+1) && (s!=0) )
		 {
		   // while count how long the next token is
		   
		   int k=0;

		   while((s[i]==' ')||(s[i]=='\t'))
			{
			  i++;
			}

   		   if (s[i]=='\0')
			break;

		   if (s[i]!='\n')
		   while((s[i]!=' ')&&(s[i]!='\t')&&(s[i]!='\n')&&(s[i]!='\0'))
			{
			  k++;
			  i++;
			}
		   else //if \n
			{
			  i++;
			  k++;
 		      }
			
		   i-=k; //we're going to recount these ones.

		   // allocate new char[] for this token
		   char temp[k+1];
		   
		   // copy it into this new char[]
		   for (int j=0;j<k;j++)
			{
			  temp[j]=s[i];
			  i++;
			}
		   temp[k]='\0'; //terminate de string
		   
		   // getop for this token
		   type = getop(temp);

		   
		   //continue as usual
	    
  	    double d0;
	    double d1;
	    int t0;
	    int t1;
	    switch (type) {
		 
 	     case '\377':
		  printf("** !eof detected! **");
		  break;
		  
	    case STRNG:
		 /** */
		 printf(" ** error: not yet implemented ** \n");
		 break;
		 
	    case GET:
		 /** check if it's a valid variable */
		 t0 = pop(); //name
		 if ((t0>=0) && (t0<26))
		   push(variable[t0]);
		 else
		   printf("\n ** error: variable %d not in range ** \n",t0);
		   /** push the variable on to the top of the stack **/
		 break;
		 
	    case SET:
		 t0 = pop(); //name
		 d0 = pop(); //value
		 if ((t0>=0) && (t0<26))
		   variable[t0]=d0;
		 else
		   printf("\n ** error: variable %d not in range ** \n",t0);
 		 dontprintme=1;
		 break;
		 /** the variables will be xa through xz */
		 /** set has two arguments, one variable, one value */
		 /** **/
	    
  	    case POW:
		 d0=pop();
		 d1=pop();
		 push(pow(d0,d1));	 
           break;

 	    case EXP:
		 d0=pop();
		 push(exp(d0));	 
           break;

	    case PEEK:
		 d0=pop();
		 d1=pop();
		 printf("\t%.8g\n",d0);
		 printf("\t%.8g\n",d1);
		 dontprintme=1;
		 push(d1);
		 push(d0);
           break;

         case SINE:
           op2=pop();
           push(sin(op2));
		 //		 printf("sin(op2): \t%.8g\n",sin(op2));
           break;

	    case SWAP:
		 d0 = pop();
		 d1 = pop();
		 push(d0);
		 push(d1);
 		 dontprintme=1;
		 break;
		 
   	    case CLEAR:
		 clear();
 		 dontprintme=1;
		 break;

   	    case DUPE:
		 d0 = pop();
		 push(d0);
 		 push(d0);
		 break;
		 
	    case NUMBER:
		 push(atof(temp));
		 break;
		 
           case '+':
               push(pop() + pop());
               break;
           case '*':
               push(pop() * pop());
               break;
           case '-':
               op2 = pop();
               push(pop() - op2);
               break;
           case '/':
               op2 = pop();
               if (op2 != 0.0)
                   push(pop() / op2);
               else
                   printf("error: zero divisor\n");
               break;
			
		 case '%':

		   t0 = pop();
		   t1 = pop();
		   if (t0 != 0)
			  push(t0%t1);
		   else
			{
			  push(t0%t1);
			  printf("this might not work, mod by 0?");
			}
		   
		   break;

      	case '\n':
		     if(dontprintme)
		   	{
		   	  dontprintme=0;
		   	  break;
		   	}

           int ferr=fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |
                        FE_UNDERFLOW);
		 if (ferr!=0)
		   {
			printf("\n ** an error occurred in the math ** \n underflow/overflow?\n");
   	          feclearexcept(FE_ALL_EXCEPT);
		   }
		   //else
		   //	{
			  outcome=pop();
			  printf("\t%.8g\n", outcome);
			  push(outcome);			  
			  //	}
               break;
           default:
               printf("error: unknown command %s\n", temp);
               break;
	    }
		 }
	    }
	   return 0;
   }
   #define MAXVAL  100  /* maximum depth of val stack */

   int sp = 0;           /* next free stack position */
   double val[MAXVAL];   /* value stack */

  void clear(void)
  {
    sp=0;
  }

   /* push:  push f onto value stack */
   void push(double f)
   {
       if (sp < MAXVAL)
           val[sp++] = f;
       else
           printf("error: stack full, can't push %g\n", f);
   }

   /* pop:  pop and return top value from stack */
   double pop(void)
   {
       if (sp > 0)
           return val[--sp];
       else {
           printf("error: stack empty\n");
           return 0.0;
       }
   }

